package com.mqb;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.io.PrintWriter;

/**
 * @author mqb
 * @date 2021/3/31 16:33
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private VerifyCodeFilter verifyCodeFilter;

    @Bean
    PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("spencer").password("123").roles("admin");
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/js/**", "/css/**", "/images/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(verifyCodeFilter, UsernamePasswordAuthenticationFilter.class);

        http.authorizeRequests()
                .antMatchers("/login.html", "/01.html", "/verifyCode").permitAll()
                .anyRequest().authenticated();

        http.formLogin()
                .loginPage("/login.html")
                .loginProcessingUrl("/login")
                .successHandler((request, response, authentication) -> {
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter writer = response.getWriter();
                    writer.write("登录成功");
                    writer.flush();
                    writer.close();
                })
                .failureHandler(authenticationFailureHandler()).permitAll()
                .and()
                .exceptionHandling()
                .authenticationEntryPoint((request, response, authException) -> {
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter writer = response.getWriter();
                    writer.write(authException.getMessage());
                    writer.flush();
                    writer.close();
                })
                .and().csrf().disable();
    }

    @Bean
    public AuthenticationFailureHandler authenticationFailureHandler() {
        return (request, response, exception) -> {
            response.setContentType("application/json;charset=utf-8");
            response.setStatus(500);
            PrintWriter writer = response.getWriter();
            String responseMsg = null;
            if (exception instanceof VerifyInvalidException) {
                responseMsg = exception.getMessage();
            } else if (exception instanceof BadCredentialsException) {
                responseMsg = "用户名或密码错误，请重新输入";
            } else if (exception instanceof LockedException) {
                responseMsg = "账户被锁定，请联系管理员";
            } else if (exception instanceof DisabledException) {
                responseMsg = "账户被禁用，请联系管理员";
            } else if (exception instanceof AccountExpiredException) {
                responseMsg = "账户过期，请联系管理员";
            } else {
                responseMsg = "账户出现问题，请联系管理员....";
            }
            writer.write(responseMsg);
            writer.flush();
            writer.close();
        };
    }
}
